package com.lgy.download;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskExecutor;

/**
 * 
 * @author fengchao 负责下载文件的管理器，由spring进行管理
 */
public class DownloadManager {
	private static Logger logger = LoggerFactory.getLogger(DownloadManager.class);
	/**
	 * 每个线程下载数目2M
	 */
	private long threadDownSize = 1024 * 1024 * 2;
	private TaskExecutor taskExecutor;

	public void setTaskExecutor(TaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}
	
	/**
	 * 
	 * <p>Title: down</p>  
	 * <p>Description: 将远程文件以流的形式写回到客户端</p>  
	 * @param res HttpServletResponse对象
	 * @param returnName 文件下载指定的名称
	 * @param fileUrl   远程文件的url
	 * @param fileSize  远程文件的大小
	 */
	public void down(HttpServletResponse res, String returnName, String fileUrl, Long fileSize) {
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpContext httpContext =  new BasicHttpContext();
		HttpGet httpGet = new HttpGet(fileUrl);
		CloseableHttpResponse response;
		try {
			response = httpclient.execute(httpGet, httpContext);
			BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent());
			byte[] buff = new byte[1024];
			int bytesRead;
			res.setContentType(DownloadUtils.getRemoteFileType(fileUrl));
			returnName = res.encodeURL(new String(returnName.getBytes(), "iso8859-1")); // 保存的文件名,必须和页面编码一致,否则乱码
			res.addHeader("Content-Disposition", "attachment;filename=" + returnName);
			res.setContentLength(fileSize.intValue());

			ServletOutputStream outputstream = res.getOutputStream(); // 取得输出流
			while ((bytesRead = bis.read(buff, 0, buff.length)) != -1) {
				outputstream.write(buff, 0, bytesRead);
			}
			outputstream.flush();
			bis.close();
		} catch (ClientProtocolException e) {
			logger.debug("文件下载 message :" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			logger.debug("文件下载 message :" + e.getMessage());
			e.printStackTrace();
		}
		logger.debug("下载完成！{} ", returnName);
	}

	/**
	 * 下载文件到指定的目录
	 * 
	 * @param localPath
	 *            指定文件的目的地址由filePath+fileName
	 * @param fileUrl
	 *            远程文件的地址
	 * @param fileSize
	 *            文件大小
	 */
	public void down(String localPath, String fileUrl, Long fileSize) {
		// 线程数据
		Long threadCount = (fileSize / threadDownSize) + (fileSize % threadDownSize != 0 ? 1 : 0);
		CountDownLatch end = new CountDownLatch(threadCount.intValue());
		CloseableHttpClient httpclient = HttpClients.createDefault();
		Long offset = 0L;
		if (fileSize <= threadDownSize) {// 如果远程文件尺寸小于等于unitSize
			DownloadThread downloadThread = new DownloadThread(fileUrl, localPath, offset, fileSize, httpclient,
					end);
			taskExecutor.execute(downloadThread);
		} else {
			for (int i = 0; i < threadCount.intValue() - 1; i++) {
				DownloadThread downloadThread = new DownloadThread(fileUrl, localPath, offset, threadDownSize,
						httpclient, end);
				offset += threadDownSize;
				taskExecutor.execute(downloadThread);
			}
			DownloadThread downloadThread = new DownloadThread(fileUrl, localPath, offset,
					fileSize - (threadCount - 1) * threadDownSize, httpclient, end);
			taskExecutor.execute(downloadThread);
		}
		try {
			end.await();
		} catch (InterruptedException e) {
			logger.error("DownLoadManager exception msg:{}", e.getMessage());
			e.printStackTrace();
		}
		logger.debug("下载完成！{} ", localPath);
	}

	
}
